<template>
  <div class="file-uploader">
    <!-- 文件选择按钮 -->
    <div class="upload-container" 
         @click="triggerFileInput" 
         @dragover.prevent="onDragOver" 
         @dragleave.prevent="onDragLeave"
         @drop.prevent="onDrop"
         :class="{ 'drag-over': isDragging }">
      
      <div v-if="!selectedFile" class="upload-prompt">
        <div class="upload-icon">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
            <path fill="none" d="M0 0h24v24H0z"/>
            <path d="M12 12.586l4.243 4.242-1.415 1.415L13 16.415V22h-2v-5.587l-1.828 1.83-1.415-1.415L12 12.586zM12 2a7.001 7.001 0 0 1 6.954 6.194 5.5 5.5 0 0 1-.953 10.784v-2.014a3.5 3.5 0 0 0 1-6.85L18 9.927V9A5 5 0 0 0 7 9v.927l-1.001.191a3.5 3.5 0 0 0 1 6.85v2.014a5.5 5.5 0 0 1-.954-10.784A7 7 0 0 1 12 2z" fill="currentColor"/>
          </svg>
        </div>
        <div class="upload-text">
          <span class="primary-text">点击或拖拽文件到此区域上传</span>
          <span class="secondary-text">
            支持的文件类型: {{ allowedTypesText }}
          </span>
          <span class="secondary-text">
            最大文件大小: {{ formatFileSize(maxFileSize) }}
          </span>
        </div>
      </div>
      
      <div v-else class="file-preview">
        <!-- 图片预览 -->
        <img v-if="fileType === 'image' && previewUrl" :src="previewUrl" class="image-preview" alt="图片预览" />
        
        <!-- 视频预览 -->
        <video v-else-if="fileType === 'video' && previewUrl" class="video-preview" controls>
          <source :src="previewUrl" :type="selectedFile.type">
          您的浏览器不支持视频播放
        </video>
        
        <!-- 文件信息 -->
        <div class="file-info">
          <div class="file-name">{{ selectedFile.name }}</div>
          <div class="file-size">{{ formatFileSize(selectedFile.size) }}</div>
          <div class="file-actions">
            <button class="btn-change" @click.stop="triggerFileInput">更换文件</button>
            <button class="btn-remove" @click.stop="removeFile">移除</button>
          </div>
        </div>
      </div>
      
      <!-- 上传进度条 -->
      <div v-if="isUploading" class="upload-progress">
        <div class="progress-bar">
          <div class="progress-fill" :style="{ width: `${uploadProgress}%` }"></div>
        </div>
        <div class="progress-text">{{ uploadProgress }}%</div>
        
        <!-- 上传控制按钮 -->
        <div class="upload-controls">
          <button v-if="!isPaused" class="btn-pause" @click.stop="pauseUpload">暂停</button>
          <button v-else class="btn-resume" @click.stop="resumeUpload">继续</button>
          <button class="btn-cancel" @click.stop="cancelUpload">取消</button>
        </div>
      </div>
    </div>
    
    <!-- 隐藏的文件输入框 -->
    <input 
      ref="fileInput"
      type="file"
      class="hidden-input"
      @change="handleFileSelect"
      :accept="acceptTypes"
    />
    
    <!-- 错误提示 -->
    <div v-if="errorMsg" class="error-message">
      <span class="error-icon">⚠️</span>
      {{ errorMsg }}
    </div>
  </div>
</template>

<script setup lang="ts">
// 导入Vue相关API
import { ref, computed, onBeforeUnmount } from 'vue'

// 定义组件接受的属性
const props = defineProps({
  // 允许的文件类型
  allowedImageTypes: {
    type: Array as () => string[],
    default: () => ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
  },
  allowedVideoTypes: {
    type: Array as () => string[],
    default: () => ['video/mp4', 'video/webm', 'video/quicktime']
  },
  // 文件大小限制（默认20MB）
  maxFileSize: {
    type: Number,
    default: 20 * 1024 * 1024 // 20MB
  },
  // 是否允许多文件上传
  multiple: {
    type: Boolean,
    default: false
  },
  // 文件上传前的验证钩子
  beforeUpload: {
    type: Function as unknown as () => (file: File) => boolean | Promise<boolean>,
    default: null
  },
  // 是否清除文件元数据
  cleanMetadata: {
    type: Boolean,
    default: true
  },
  // 是否过滤有害内容
  filterHarmfulContent: {
    type: Boolean,
    default: true
  },
  // 自动上传
  autoUpload: {
    type: Boolean,
    default: true
  },
  // 文件类型限制（'image', 'video', 'all'）
  fileTypeLimit: {
    type: String,
    default: 'all',
    validator: (value: string) => ['image', 'video', 'all'].includes(value)
  },
  // 分片上传设置
  chunkSize: {
    type: Number,
    default: 2 * 1024 * 1024 // 默认分片大小为2MB
  },
  // 上传API地址
  uploadUrl: {
    type: String,
    default: '/api/upload'
  },
  // 最大自动重试次数
  maxRetries: {
    type: Number,
    default: 3
  },
  // 重试延迟(毫秒)
  retryDelay: {
    type: Number,
    default: 1000
  }
})

// 定义组件触发的事件
const emit = defineEmits([
  'file-selected', // 当文件被选择时触发
  'file-validated', // 当文件验证通过时触发
  'validation-failed', // 当文件验证失败时触发
  'upload-progress', // 上传进度更新时触发
  'upload-success', // 上传成功时触发
  'upload-error', // 上传失败时触发
  'upload-cancelled', // 上传被取消时触发
  'file-removed', // 文件被移除时触发
  'retry-attempt', // 重试上传时触发
  'chunk-success', // 分片上传成功时触发
  'chunk-error' // 分片上传失败时触发
])

// 组件内部状态
const fileInput = ref<HTMLInputElement | null>(null) // 文件输入框引用
const selectedFile = ref<File | null>(null) // 当前选择的文件
const previewUrl = ref<string>('') // 文件预览URL
const fileType = ref<'image' | 'video' | null>(null) // 当前文件类型
const errorMsg = ref<string>('') // 错误消息
const isDragging = ref<boolean>(false) // 是否正在拖拽

// 上传相关状态
const isUploading = ref<boolean>(false) // 是否正在上传
const uploadProgress = ref<number>(0) // 上传进度
const isPaused = ref<boolean>(false) // 是否已暂停上传
const retryCount = ref<number>(0) // 当前重试次数
const uploadChunks = ref<any[]>([]) // 存储分片信息
const currentChunkIndex = ref<number>(0) // 当前上传的分片索引
const totalChunks = ref<number>(0) // 总分片数
const uploadId = ref<string>('') // 上传ID，用于标识一次完整的上传

// 计算属性：接受的文件类型字符串（用于input的accept属性）
const acceptTypes = computed(() => {
  const types = []
  if (props.fileTypeLimit === 'all' || props.fileTypeLimit === 'image') {
    types.push(...props.allowedImageTypes)
  }
  if (props.fileTypeLimit === 'all' || props.fileTypeLimit === 'video') {
    types.push(...props.allowedVideoTypes)
  }
  return types.join(',')
})

// 计算属性：允许的文件类型文本
const allowedTypesText = computed(() => {
  const imageExtensions: string[] = []
  const videoExtensions: string[] = []
  
  // 提取图片扩展名
  if (props.fileTypeLimit === 'all' || props.fileTypeLimit === 'image') {
    props.allowedImageTypes.forEach(type => {
      const ext = type.split('/')[1]
      if (ext && !imageExtensions.includes(ext)) {
        imageExtensions.push(ext)
      }
    })
  }
  
  // 提取视频扩展名
  if (props.fileTypeLimit === 'all' || props.fileTypeLimit === 'video') {
    props.allowedVideoTypes.forEach(type => {
      const ext = type.split('/')[1]
      if (ext && !videoExtensions.includes(ext)) {
        videoExtensions.push(ext)
      }
    })
  }
  
  // 组合文本
  const parts = []
  if (imageExtensions.length > 0) {
    parts.push(`图片(${imageExtensions.join(', ')})`)
  }
  if (videoExtensions.length > 0) {
    parts.push(`视频(${videoExtensions.join(', ')})`)
  }
  
  return parts.join('，')
})

// 触发文件选择对话框
function triggerFileInput() {
  if (fileInput.value) {
    fileInput.value.click()
  }
}

// 处理文件选择
async function handleFileSelect(event: Event) {
  // 清除错误消息
  errorMsg.value = ''
  
  // 获取选择的文件
  const input = event.target as HTMLInputElement
  const files = input.files
  
  // 如果没有选择文件，直接返回
  if (!files || files.length === 0) {
    return
  }
  
  const file = files[0]
  
  // 触发文件选择事件
  emit('file-selected', file)
  
  try {
    // 进行文件验证
    if (await validateFile(file)) {
      // 过滤有害内容(如果启用)
      let processedFile = file
      
      if (props.filterHarmfulContent) {
        const isContentSafe = await filterHarmfulContent(file)
        if (!isContentSafe) {
          errorMsg.value = '文件包含不适当内容，无法上传'
          emit('validation-failed', { file, reason: 'harmful-content', message: errorMsg.value })
          return
        }
      }
      
      // 清除元数据(如果启用)
      if (props.cleanMetadata) {
        try {
          processedFile = await cleanFileMetadata(file)
        } catch (error) {
          console.warn('清除文件元数据失败:', error)
          // 元数据清除失败时，继续使用原始文件
          processedFile = file
        }
      }
      
      // 处理文件预览
      handleFilePreview(processedFile)
      
      // 自动上传
      if (props.autoUpload) {
        startUpload()
      }
    }
  } catch (error) {
    console.error('文件处理错误:', error)
    errorMsg.value = '文件处理过程中发生错误'
  }
  
  // 重置文件输入，以便可以再次选择相同的文件
  if (input) {
    input.value = ''
  }
}

// 文件验证
async function validateFile(file: File): Promise<boolean> {
  try {
    // 文件类型验证
    if (!validateFileType(file)) {
      errorMsg.value = `不支持的文件类型：${file.type}`
      emit('validation-failed', { file, reason: 'type', message: errorMsg.value })
      return false
    }
    
    // 文件大小验证
    if (file.size > props.maxFileSize) {
      errorMsg.value = `文件大小超过限制（${formatFileSize(file.size)}，最大允许${formatFileSize(props.maxFileSize)}）`
      emit('validation-failed', { file, reason: 'size', message: errorMsg.value })
      return false
    }
    
    // 检查文件名是否包含敏感字符或可执行扩展名
    const dangerousExtensions = ['.exe', '.bat', '.cmd', '.sh', '.php', '.js']
    const fileExt = file.name.substring(file.name.lastIndexOf('.')).toLowerCase()
    if (dangerousExtensions.includes(fileExt)) {
      errorMsg.value = `不允许上传可能有安全风险的文件类型: ${fileExt}`
      emit('validation-failed', { file, reason: 'security', message: errorMsg.value })
      return false
    }
    
    // 如果提供了自定义验证函数，使用它进行进一步验证
    if (props.beforeUpload) {
      const result = await Promise.resolve(props.beforeUpload(file))
      if (!result) {
        errorMsg.value = '文件未通过自定义验证'
        emit('validation-failed', { file, reason: 'custom', message: errorMsg.value })
        return false
      }
    }
    
    // 所有验证通过
    emit('file-validated', file)
    return true
  } catch (error) {
    errorMsg.value = '文件验证过程中发生错误'
    console.error('文件验证错误:', error)
    emit('validation-failed', { file, reason: 'error', message: errorMsg.value })
    return false
  }
}

// 验证文件类型
function validateFileType(file: File): boolean {
  // 根据文件类型限制筛选允许的类型
  const allowedTypes = []
  if (props.fileTypeLimit === 'all' || props.fileTypeLimit === 'image') {
    allowedTypes.push(...props.allowedImageTypes)
  }
  if (props.fileTypeLimit === 'all' || props.fileTypeLimit === 'video') {
    allowedTypes.push(...props.allowedVideoTypes)
  }
  
  return allowedTypes.includes(file.type)
}

// 获取文件类型
function getFileType(file: File): 'image' | 'video' | null {
  if (props.allowedImageTypes.includes(file.type)) {
    return 'image'
  } else if (props.allowedVideoTypes.includes(file.type)) {
    return 'video'
  }
  return null
}

// 处理文件预览
function handleFilePreview(file: File) {
  // 获取文件类型
  const type = getFileType(file)
  
  // 如果文件类型无效，不处理
  if (!type) {
    return
  }
  
  // 更新状态
  selectedFile.value = file
  fileType.value = type
  
  // 创建预览URL
  if (previewUrl.value) {
    // 如果已有预览URL，先释放
    URL.revokeObjectURL(previewUrl.value)
  }
  previewUrl.value = URL.createObjectURL(file)
}

// 移除文件
function removeFile() {
  // 如果正在上传，先取消上传
  if (isUploading.value) {
    cancelUpload()
  }
  
  // 释放预览URL
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value)
    previewUrl.value = ''
  }
  
  // 重置状态
  selectedFile.value = null
  fileType.value = null
  errorMsg.value = ''
  
  // 触发文件移除事件
  emit('file-removed')
}

// 开始上传
function startUpload() {
  if (!selectedFile.value || isUploading.value) {
    return
  }
  
  isUploading.value = true
  uploadProgress.value = 0
  isPaused.value = false
  retryCount.value = 0
  
  // 如果文件大小小于分片大小，直接上传整个文件
  if (selectedFile.value.size <= props.chunkSize) {
    uploadWholeFile(selectedFile.value)
  } else {
    // 否则，进行分片上传
    prepareChunks(selectedFile.value)
    uploadNextChunk()
  }
}

// 准备分片
function prepareChunks(file: File) {
  const chunks = []
  const chunkSize = props.chunkSize
  const fileSize = file.size
  const chunkCount = Math.ceil(fileSize / chunkSize)
  totalChunks.value = chunkCount
  currentChunkIndex.value = 0
  
  // 生成上传ID
  uploadId.value = generateUploadId()
  
  // 分割文件
  for (let i = 0; i < chunkCount; i++) {
    const start = i * chunkSize
    const end = Math.min(fileSize, start + chunkSize)
    
    chunks.push({
      index: i,
      file: file.slice(start, end),
      start,
      end,
      status: 'pending', // pending, uploading, success, error
      progress: 0,
      retries: 0
    })
  }
  
  uploadChunks.value = chunks
}

// 生成上传ID
function generateUploadId() {
  return `upload_${Date.now()}_${Math.floor(Math.random() * 1000000)}`
}

// 上传下一个分片
function uploadNextChunk() {
  if (isPaused.value || !isUploading.value) {
    return
  }
  
  // 检查是否所有分片都已上传
  const pendingChunks = uploadChunks.value.filter(chunk => chunk.status !== 'success')
  
  if (pendingChunks.length === 0) {
    // 所有分片上传成功，合并文件
    mergeChunks()
    return
  }
  
  // 找到下一个待上传的分片
  const nextChunk = pendingChunks.find(chunk => chunk.status === 'pending') || 
                    pendingChunks.find(chunk => chunk.status === 'error')
  
  if (!nextChunk) {
    return
  }
  
  // 更新分片状态
  nextChunk.status = 'uploading'
  currentChunkIndex.value = nextChunk.index
  
  // 上传分片
  uploadChunk(nextChunk)
}

// 上传单个分片
function uploadChunk(chunk: any) {
  // 实际项目中，这里应该发送HTTP请求上传分片
  // 以下是模拟上传过程
  
  // 创建表单数据
  const formData = new FormData()
  formData.append('file', chunk.file)
  formData.append('chunk_index', chunk.index.toString())
  formData.append('total_chunks', totalChunks.value.toString())
  formData.append('upload_id', uploadId.value)
  formData.append('filename', selectedFile.value?.name || '')
  
  // 在实际项目中，使用以下代码上传分片
  /*
  // 创建XHR对象
  const xhr = new XMLHttpRequest()
  
  // 监听上传进度
  xhr.upload.addEventListener('progress', (e) => {
    if (e.lengthComputable) {
      const chunkProgress = Math.round((e.loaded / e.total) * 100)
      chunk.progress = chunkProgress
      updateTotalProgress()
    }
  })
  
  // 监听请求完成
  xhr.addEventListener('load', () => {
    if (xhr.status >= 200 && xhr.status < 300) {
      // 上传成功
      chunk.status = 'success'
      chunk.progress = 100
      emit('chunk-success', { chunk, response: xhr.response })
      updateTotalProgress()
      uploadNextChunk()
    } else {
      // 上传失败
      chunk.status = 'error'
      emit('chunk-error', { chunk, error: xhr.statusText })
      retryChunk(chunk)
    }
  })
  
  // 监听请求错误
  xhr.addEventListener('error', () => {
    chunk.status = 'error'
    emit('chunk-error', { chunk, error: 'Network error' })
    retryChunk(chunk)
  })
  
  // 监听请求中止
  xhr.addEventListener('abort', () => {
    chunk.status = 'error'
  })
  
  // 发送请求
  xhr.open('POST', props.uploadUrl)
  xhr.send(formData)
  */
  
  // 模拟上传过程
  simulateChunkUpload(chunk)
}

// 模拟分片上传过程
function simulateChunkUpload(chunk: any) {
  // 随机决定是否模拟上传失败
  const shouldFail = Math.random() < 0.3 // 30%概率失败
  
  const totalTime = 2000 + Math.random() * 2000 // 2-4秒完成
  const startTime = Date.now()
  const progressInterval = setInterval(() => {
    // 如果已暂停或取消上传，停止更新
    if (isPaused.value || !isUploading.value) {
      clearInterval(progressInterval)
      return
    }
    
    const elapsedTime = Date.now() - startTime
    const progress = Math.min(Math.floor((elapsedTime / totalTime) * 100), 99)
    
    // 更新分片进度
    chunk.progress = progress
    updateTotalProgress()
    
    // 当进度达到99%时
    if (progress >= 99) {
      clearInterval(progressInterval)
      
      // 延迟一会儿，模拟服务器处理时间
      setTimeout(() => {
        if (shouldFail && chunk.retries < props.maxRetries) {
          // 模拟上传失败
          chunk.status = 'error'
          emit('chunk-error', { 
            chunk, 
            error: '网络错误，准备重试' 
          })
          retryChunk(chunk)
        } else {
          // 模拟上传成功
          chunk.status = 'success'
          chunk.progress = 100
          emit('chunk-success', { 
            chunk, 
            response: { status: 'success', chunkIndex: chunk.index } 
          })
          updateTotalProgress()
          
          // 上传下一个分片
          uploadNextChunk()
        }
      }, 500)
    }
  }, 200)
}

// 更新总进度
function updateTotalProgress() {
  // 计算总体上传进度
  const chunks = uploadChunks.value
  if (chunks.length === 0) return
  
  let totalProgress = 0
  chunks.forEach(chunk => {
    totalProgress += chunk.progress
  })
  
  uploadProgress.value = Math.floor(totalProgress / chunks.length)
  emit('upload-progress', uploadProgress.value)
  
  // 如果总进度达到100%，表示上传完成
  if (uploadProgress.value >= 100) {
    // 触发上传成功事件
    emit('upload-success', {
      file: selectedFile.value,
      response: { status: 'success', uploadId: uploadId.value }
    })
    
    // 2秒后重置上传状态
    setTimeout(() => {
      isUploading.value = false
    }, 2000)
  }
}

// 重试上传分片
function retryChunk(chunk: any) {
  // 如果超过最大重试次数，将分片标记为错误
  if (chunk.retries >= props.maxRetries) {
    errorMsg.value = `分片 ${chunk.index + 1} 上传失败，已达到最大重试次数`
    return
  }
  
  chunk.retries++
  retryCount.value++
  
  // 触发重试事件
  emit('retry-attempt', { 
    chunk, 
    retryCount: chunk.retries,
    totalRetries: retryCount.value
  })
  
  // 标记为待上传
  chunk.status = 'pending'
  
  // 延迟一段时间后重试
  setTimeout(() => {
    if (isUploading.value && !isPaused.value) {
      uploadNextChunk()
    }
  }, props.retryDelay * chunk.retries) // 使用指数退避策略
}

// 合并分片
function mergeChunks() {
  // 在实际项目中，这里应该发送请求到服务器合并分片
  // 这里仅模拟合并过程
  
  uploadProgress.value = 100
  emit('upload-progress', 100)
  
  // 触发上传成功事件
  emit('upload-success', {
    file: selectedFile.value,
    response: { status: 'success', uploadId: uploadId.value }
  })
  
  // 2秒后重置上传状态
  setTimeout(() => {
    isUploading.value = false
  }, 2000)
}

// 上传整个文件（不分片）
function uploadWholeFile(file: File) {
  // 实际项目中，这里应该发送HTTP请求上传文件
  // 这里仅模拟上传过程
  simulateUploadProgress()
}

// 暂停上传
function pauseUpload() {
  if (isUploading.value) {
    isPaused.value = true
  }
}

// 恢复上传
function resumeUpload() {
  if (isUploading.value && isPaused.value) {
    isPaused.value = false
    uploadNextChunk() // 继续上传未完成的分片
  }
}

// 取消上传
function cancelUpload() {
  if (isUploading.value) {
    isUploading.value = false
    uploadProgress.value = 0
    isPaused.value = false
    retryCount.value = 0
    
    // 触发上传取消事件
    emit('upload-cancelled')
  }
}

// 拖拽相关处理
function onDragOver(event: DragEvent) {
  event.preventDefault()
  isDragging.value = true
}

function onDragLeave() {
  isDragging.value = false
}

function onDrop(event: DragEvent) {
  event.preventDefault()
  isDragging.value = false
  
  // 获取拖拽的文件
  const files = event.dataTransfer?.files
  if (files && files.length > 0) {
    // 模拟文件选择事件
    const file = files[0]
    
    // 触发文件选择事件
    emit('file-selected', file)
    
    // 进行文件验证
    validateFile(file).then(isValid => {
      if (isValid) {
        // 处理文件预览
        handleFilePreview(file)
        
        // 自动上传
        if (props.autoUpload) {
          startUpload()
        }
      }
    })
  }
}

// 格式化文件大小
function formatFileSize(bytes: number): string {
  if (bytes < 1024) {
    return bytes + ' B'
  } else if (bytes < 1024 * 1024) {
    return (bytes / 1024).toFixed(1) + ' KB'
  } else if (bytes < 1024 * 1024 * 1024) {
    return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
  } else {
    return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB'
  }
}

// 过滤有害内容
async function filterHarmfulContent(file: File): Promise<boolean> {
  // 检查文件类型，确保为支持的类型
  if (!['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'video/mp4', 'video/webm'].includes(file.type)) {
    return true; // 非媒体文件不需要内容检查
  }
  
  // 对于图片文件，可以创建临时预览并分析内容
  if (file.type.startsWith('image/')) {
    return new Promise((resolve) => {
      const img = new Image();
      img.onload = () => {
        // 创建canvas进行图像分析
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        canvas.width = img.width;
        canvas.height = img.height;
        ctx?.drawImage(img, 0, 0);
        
        // 此处可以添加图像分析算法
        // 例如：皮肤色调检测、特征检测、与已知有害内容数据库比对等
        
        // 在实际项目中，这里可以调用AI内容审核API
        // 例如调用腾讯云、阿里云或其他厂商的内容审核API
        
        // 示例：模拟内容检测
        // const isHarmful = detectHarmfulImageContent(canvas);
        // 这里暂时直接返回通过
        
        // 清理资源
        URL.revokeObjectURL(img.src);
        resolve(true);
      };
      img.onerror = () => resolve(false);
      img.src = URL.createObjectURL(file);
    });
  }
  
  // 对于视频文件，可以抽取帧进行分析或使用API
  if (file.type.startsWith('video/')) {
    try {
      // 读取文件头部字节，验证是否为有效的视频文件
      const headerBytes = await readFileHeader(file, 16);
      const isValidVideo = validateVideoFileSignature(headerBytes, file.type);
      
      if (!isValidVideo) {
        return false;
      }
      
      // 此处可以添加视频内容检测逻辑
      // 例如：抽取视频帧进行分析、调用视频内容审核API等
      
      // 在实际项目中，可能需要将视频上传到服务端进行内容审核
      
      return true;
    } catch (error) {
      console.error("视频验证失败:", error);
      return false;
    }
  }
  
  return true;
}

// 读取文件头部字节
function readFileHeader(file: File, byteCount: number): Promise<ArrayBuffer> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => resolve(e.target?.result as ArrayBuffer);
    reader.onerror = reject;
    reader.readAsArrayBuffer(file.slice(0, byteCount));
  });
}

// 验证视频文件签名
function validateVideoFileSignature(header: ArrayBuffer, mimeType: string): boolean {
  const bytes = new Uint8Array(header);
  
  // 检查MP4文件头 (通常以 'ftyp' 标记开始)
  if (mimeType === 'video/mp4') {
    // MP4文件头检查：查找"ftyp"标记
    for (let i = 0; i < bytes.length - 4; i++) {
      if (bytes[i] === 0x66 && bytes[i+1] === 0x74 && 
          bytes[i+2] === 0x79 && bytes[i+3] === 0x70) {
        return true;
      }
    }
    return false;
  }
  
  // WebM格式检查（通常以EBML头开始）
  if (mimeType === 'video/webm') {
    // WebM文件头开始于0x1A 0x45 0xDF 0xA3
    if (bytes[0] === 0x1A && bytes[1] === 0x45 && 
        bytes[2] === 0xDF && bytes[3] === 0xA3) {
      return true;
    }
    return false;
  }
  
  // 其他视频格式的检查可以添加在这里
  return true;
}

// 清除文件元数据
async function cleanFileMetadata(file: File): Promise<File> {
  // 根据文件类型选择不同的清理方法
  if (file.type.startsWith('image/')) {
    return cleanImageMetadata(file);
  } else if (file.type.startsWith('video/')) {
    return cleanVideoMetadata(file);
  }
  
  // 其他类型文件直接返回
  return file;
}

// 清除图片元数据
async function cleanImageMetadata(file: File): Promise<File> {
  return new Promise((resolve, reject) => {
    // 创建一个新的图像对象
    const img = new Image();
    img.onload = () => {
      // 使用canvas重新绘制图像，这会丢弃原始元数据
      const canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext('2d');
      ctx?.drawImage(img, 0, 0);
      
      // 转换canvas为Blob
      canvas.toBlob((blob) => {
        if (blob) {
          // 创建新的File对象，保持原文件名和类型
          const cleanedFile = new File([blob], file.name, { 
            type: file.type,
            lastModified: new Date().getTime()
          });
          
          // 清理资源
          URL.revokeObjectURL(img.src);
          resolve(cleanedFile);
        } else {
          reject(new Error('Failed to create blob from canvas'));
        }
      }, file.type);
    };
    
    img.onerror = () => reject(new Error('Failed to load image'));
    img.src = URL.createObjectURL(file);
  });
}

// 清除视频元数据
async function cleanVideoMetadata(file: File): Promise<File> {
  // 注意：在浏览器端完全清除视频元数据比较复杂
  // 通常需要服务器端处理或使用专门的库
  
  // 以下是一个简化的处理方案，实际实现可能需要更复杂的处理
  // 或者依赖服务器端处理
  
  // 在实际项目中，可以：
  // 1. 使用MediaRecorder API重新录制视频（会丢失一些元数据）
  // 2. 使用Web Assembly加载的FFmpeg处理视频
  // 3. 上传到服务器处理后再返回
  
  // 简化示例 - 在生产环境中应该使用更完善的处理
  console.log('视频元数据清理功能需要在服务端实现，目前前端仅支持图片元数据清理');
  return file;
}

// 模拟上传进度（用于不分片上传时）
function simulateUploadProgress() {
  // 模拟进度更新的间隔（毫秒）
  const updateInterval = 200
  // 每次更新的进度增量（随机）
  const minIncrement = 2
  const maxIncrement = 10
  
  const timer = setInterval(() => {
    // 如果已暂停，不更新进度
    if (isPaused.value) {
      return
    }
    
    // 如果已取消上传或者没有选择文件，清除定时器
    if (!isUploading.value || !selectedFile.value) {
      clearInterval(timer)
      return
    }
    
    // 随机增加进度
    const increment = Math.floor(Math.random() * (maxIncrement - minIncrement + 1)) + minIncrement
    
    // 更新进度，最高到99%（留1%给上传完成操作）
    uploadProgress.value = Math.min(uploadProgress.value + increment, 99)
    
    // 触发进度更新事件
    emit('upload-progress', uploadProgress.value)
    
    // 如果进度达到99%，模拟完成上传
    if (uploadProgress.value >= 99) {
      clearInterval(timer)
      
      // 延迟一会儿，模拟服务器处理时间
      setTimeout(() => {
        // 设置进度为100%，表示上传完成
        uploadProgress.value = 100
        
        // 触发上传成功事件
        emit('upload-success', {
          file: selectedFile.value,
          response: { status: 'success', url: previewUrl.value }
        })
        
        // 2秒后自动重置上传状态
        setTimeout(() => {
          isUploading.value = false
        }, 2000)
      }, 500)
    }
  }, updateInterval)
  
  // 存储定时器ID，以便在组件销毁时清除
  uploadTimer.value = timer
}

// 存储上传进度模拟的定时器ID
const uploadTimer = ref<ReturnType<typeof setInterval> | null>(null)

// 组件销毁时清理资源
onBeforeUnmount(() => {
  // 清除预览URL
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value)
  }
  
  // 清除定时器
  if (uploadTimer.value !== null) {
    clearInterval(uploadTimer.value)
  }
})

// 暴露组件方法给父组件
defineExpose({
  triggerFileInput,
  validateFile,
  handleFilePreview,
  removeFile,
  startUpload,
  pauseUpload,
  resumeUpload,
  cancelUpload,
  filterHarmfulContent,
  cleanFileMetadata,
  uploadNextChunk,
  retryChunk
})
</script>

<style scoped>
.file-uploader {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  max-width: 100%;
  width: 100%;
}

.upload-container {
  border: 2px dashed #ccc;
  border-radius: 8px;
  padding: 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s;
  position: relative;
  min-height: 150px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.upload-container:hover {
  border-color: #1890ff;
  background-color: rgba(24, 144, 255, 0.05);
}

.drag-over {
  border-color: #1890ff;
  background-color: rgba(24, 144, 255, 0.1);
}

.upload-prompt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.upload-icon {
  font-size: 32px;
  color: #1890ff;
  margin-bottom: 8px;
}

.upload-icon svg {
  width: 48px;
  height: 48px;
  fill: #1890ff;
}

.upload-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.primary-text {
  font-size: 16px;
  font-weight: 500;
  color: #333;
}

.secondary-text {
  font-size: 14px;
  color: #666;
}

.file-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
}

.image-preview, .video-preview {
  max-width: 100%;
  max-height: 200px;
  border-radius: 4px;
  object-fit: contain;
}

.file-info {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.file-name {
  font-size: 16px;
  font-weight: 500;
  word-break: break-word;
}

.file-size {
  font-size: 14px;
  color: #666;
}

.file-actions {
  display: flex;
  gap: 12px;
  margin-top: 8px;
}

.upload-progress {
  width: 100%;
  margin-top: 16px;
}

.progress-bar {
  width: 100%;
  height: 6px;
  background-color: #f0f0f0;
  border-radius: 3px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background-color: #1890ff;
  transition: width 0.3s;
}

.progress-text {
  margin-top: 4px;
  font-size: 14px;
  color: #666;
  text-align: center;
}

.upload-controls {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 8px;
}

.hidden-input {
  display: none;
}

.error-message {
  margin-top: 8px;
  padding: 8px 12px;
  color: #ff4d4f;
  background-color: #fff2f0;
  border: 1px solid #ffccc7;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}

.error-icon {
  font-size: 16px;
}

button {
  padding: 6px 12px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background-color: white;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 14px;
}

.btn-change {
  color: #1890ff;
  border-color: #1890ff;
}

.btn-change:hover {
  background-color: rgba(24, 144, 255, 0.1);
}

.btn-remove {
  color: #ff4d4f;
  border-color: #ff4d4f;
}

.btn-remove:hover {
  background-color: rgba(255, 77, 79, 0.1);
}

.btn-pause, .btn-resume {
  color: #faad14;
  border-color: #faad14;
}

.btn-pause:hover, .btn-resume:hover {
  background-color: rgba(250, 173, 20, 0.1);
}

.btn-cancel {
  color: #ff4d4f;
  border-color: #ff4d4f;
}

.btn-cancel:hover {
  background-color: rgba(255, 77, 79, 0.1);
}
</style> 